package com.xhui.vimarket.zkplus.utils;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.SuspendNotAllowedException;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.Iframe;
import org.zkoss.zul.Window;

import com.xhui.vimarket.common.exception.RtManagerException;

/**
 * ZkWindUtil.
 * 
 * @author wuyx
 * @version Revision 1.0.0
 */
public final class ZkWindUtil {
    /**
     * POSITION_PREV.
     */
    public static final String POSITION_PREV      = "prev";
    /**
     * POSITION_NEXT.
     */
    public static final String POSITION_NEXT      = "next";
    /**
     * POP_CONTAINER.
     */
    public static final String POP_CONTAINER      = "POP_CONTAINER";
    /**
     * 大窗口宽度，高度.
     */
    public static final int    WIN_MAX_SIZE       = 1;
    /**
     * WIN_MAX_WIDTH.
     */
    public static final int    WIN_MAX_WIDTH      = 860;
    /**
     * WIN_MAX_HEIGHT.
     */
    public static final int    WIN_MAX_HEIGHT     = 480;
    /**
     * WIN_FULL_WIDTH_STR.
     */
    public static final String WIN_FULL_WIDTH_STR = "960px";
    /**
     * WIN_MAX_WIDTH_STR.
     */
    public static final String WIN_MAX_WIDTH_STR  = "860px";
    /**
     * WIN_MAX_HEIGHT_STR.
     */
    public static final String WIN_MAX_HEIGHT_STR = "480px";
    
    /**
     * 中窗口宽度，高度.
     */
    public static final int    WIN_MID_SIZE       = 2;
    /**
     * WIN_MID_WIDTH.
     */
    public static final int    WIN_MID_WIDTH      = 680;
    /**
     * WIN_MID_HEIGHT.
     */
    public static final int    WIN_MID_HEIGHT     = 400;
    /**
     * WIN_MID_WIDTH_STR.
     */
    public static final String WIN_MID_WIDTH_STR  = "680px";
    /**
     * WIN_MID_HEIGHT_STR.
     */
    public static final String WIN_MID_HEIGHT_STR = "400px";
    
    /**
     * 小窗口宽度，高度.
     */
    public static final int    WIN_MIN_SIZE       = 3;
    /**
     * WIN_MIN_WIDTH.
     */
    public static final int    WIN_MIN_WIDTH      = 480;
    /**
     * WIN_MIN_HEIGHT.
     */
    public static final int    WIN_MIN_HEIGHT     = 320;
    /**
     * WIN_MIN_WIDTH_STR.
     */
    public static final String WIN_MIN_WIDTH_STR  = "480px";
    /**
     * WIN_MIN_HEIGHT_STR.
     */
    public static final String WIN_MIN_HEIGHT_STR = "320px";
    /**
     * WIN_ONECELL_HEIGHT.
     */
    public static final int    WIN_ONECELL_HEIGH  = 50;
    /**
     * 自动窗口宽度，高度.
     */
    public static final int    WIN_AUTO_SIZE      = -1;
    /**
     * 自动窗口宽度，高度.
     */
    public static final String WIN_AUTO_SIZE_STR  = "-1";
    /**
     * 自动窗口宽度，高度.
     */
    public static final String WIN_OP_TYPE_OPEN   = "open";
    /**
     * 自动窗口宽度，高度.
     */
    public static final String WIN_OP_TYPE_SELF   = "self";
    
    /**
     * 私有构造函数.
     */
    private ZkWindUtil() {
    }
    
    /**
     * doModal.
     * 
     * @param win
     *            Window
     */
    public static void doModal(final Window win) {
        ZkWindUtil.doModal(win, ZkWindUtil.WIN_MID_SIZE);
    }
    
    /**
     * doModal.
     * 
     * @param num
     *            int
     *            @return int
     */
    public static int getCell(final int num) {
        return WIN_ONECELL_HEIGH * num;
    }
    
    /**
     * doModal.
     * 
     * @param num
     *            int
     *            @return String
     */
    public static String getCellStr(final int num) {
        return WIN_ONECELL_HEIGH * num + "px";
    }
    
    /**
     * doModal.
     * 
     * @param win
     *            Window
     * @param size
     *            size
     */
    public static void doModal(final Window win, final int size) {
        if (win == null) {
            throw new RtManagerException("打开窗口异常，传入的窗口为空", ZkWindUtil.class, "doModal", "winNull");
        }
        win.setClosable(true);
        win.setSizable(true);
        if (size == ZkWindUtil.WIN_MAX_SIZE) {
            ZkWindUtil.doModal(win, ZkWindUtil.WIN_MAX_WIDTH_STR, ZkWindUtil.WIN_MAX_HEIGHT_STR);
        } else if (size == ZkWindUtil.WIN_MIN_SIZE) {
            ZkWindUtil.doModal(win, ZkWindUtil.WIN_MIN_WIDTH_STR, ZkWindUtil.WIN_MIN_HEIGHT_STR);
        } else {
            ZkWindUtil.doModal(win, ZkWindUtil.WIN_MID_WIDTH_STR, ZkWindUtil.WIN_MID_HEIGHT_STR);
        }
    }
    
    /**
     * doModal.
     * 
     * @param win
     *            Window
     * @param w
     *            String
     * @param h
     *            String
     */
    public static void doModal(final Window win, final String w, final String h) {
        if (!ZkWindUtil.WIN_AUTO_SIZE_STR.equals(w)) {
            win.setWidth(w);
        }
        if (!ZkWindUtil.WIN_AUTO_SIZE_STR.equals(h)) {
            win.setHeight(h);
        }
        try {
            win.doModal();
        } catch (final SuspendNotAllowedException e) {
            throw new RtManagerException("打开窗口异常，窗口@win", ZkWindUtil.class, "doModal",
                "SuspendNotAllowedException", "@win", win.getTitle());
        }
    }
    
    /**
     * doModal.
     * 
     * @param win
     *            Window
     * @param size
     *            size
     */
    public static void doOverlapped(final Window win, final int size) {
        if (win == null) {
            throw new RtManagerException("打开窗口异常，传入的窗口为空", ZkWindUtil.class, "doModal", "winNull");
        }
        win.setClosable(true);
        win.setSizable(true);
        if (size == ZkWindUtil.WIN_MAX_SIZE) {
            ZkWindUtil.doOverlapped(win, ZkWindUtil.WIN_MAX_WIDTH_STR,
                ZkWindUtil.WIN_MAX_HEIGHT_STR);
        } else if (size == ZkWindUtil.WIN_MIN_SIZE) {
            ZkWindUtil.doOverlapped(win, ZkWindUtil.WIN_MIN_WIDTH_STR,
                ZkWindUtil.WIN_MIN_HEIGHT_STR);
        } else {
            ZkWindUtil.doOverlapped(win, ZkWindUtil.WIN_MID_WIDTH_STR,
                ZkWindUtil.WIN_MID_HEIGHT_STR);
        }
    }
    
    /**
     * doModal.
     * 
     * @param win
     *            Window
     * @param w
     *            String
     * @param h
     *            String
     */
    public static void doOverlapped(final Window win, final String w, final String h) {
        if (!ZkWindUtil.WIN_AUTO_SIZE_STR.equals(w)) {
            win.setWidth(w);
        }
        if (!ZkWindUtil.WIN_AUTO_SIZE_STR.equals(h)) {
            win.setHeight(h);
        }
        win.doOverlapped();
    }
    
    /**
     * createPopup.
     * 
     * @param popCompUrl String
     * @param args Map
     * @param w String
     * @param h String
     * @param selfComp Component
     * @param position String
     * @return Window
     * @author wuyx
     * 2011-3-1 wuyx 
     */
    public static Window createPopup(final String popCompUrl, final Map<String, Object> args,
        final String w, final String h, final Component selfComp, final String position) {
        // get popup win
        Window popWin = ZkWindUtil.getAutoWind(selfComp, position);
        if (popWin == null) {
            // create real win
            final Window subWin = (Window) Executions.createComponents(popCompUrl, null, args);
            popWin = ZkWindUtil.putAutoWind(selfComp, position, subWin);
        }
        // opoup
        ZkWindUtil.doPopup((Window) popWin.getFirstChild(), w, h);
        return popWin;
    }
    
    /**
     * doModal.
     * 
     * @param win
     *            Window
     * @param size
     *            size
     */
    public static void doPopup(final Window win, final int size) {
        if (win == null) {
            throw new RtManagerException("打开窗口异常，传入的窗口为空", ZkWindUtil.class, "doModal", "winNull");
        }
        win.setClosable(true);
        win.setSizable(true);
        if (size == ZkWindUtil.WIN_MAX_SIZE) {
            ZkWindUtil.doPopup(win, ZkWindUtil.WIN_MAX_WIDTH_STR, ZkWindUtil.WIN_MAX_HEIGHT_STR);
        } else if (size == ZkWindUtil.WIN_MIN_SIZE) {
            ZkWindUtil.doPopup(win, ZkWindUtil.WIN_MIN_WIDTH_STR, ZkWindUtil.WIN_MIN_HEIGHT_STR);
        } else if (size == ZkWindUtil.WIN_MID_SIZE) {
            ZkWindUtil.doPopup(win, ZkWindUtil.WIN_MID_WIDTH_STR, ZkWindUtil.WIN_MID_HEIGHT_STR);
        } else {
            win.doPopup();
        }
    }
    
    /**
     * doModal.
     * 
     * @param win
     *            Window
     * @param w
     *            String
     * @param h
     *            String
     */
    public static void doPopup(final Window win, final String w, final String h) {
        if (!ZkWindUtil.WIN_AUTO_SIZE_STR.equals(w)) {
            win.setWidth(w);
        }
        if (!ZkWindUtil.WIN_AUTO_SIZE_STR.equals(h)) {
            win.setHeight(h);
        }
        win.doPopup();
    }
    
    /**
     * 生成浮动窗口.
     * 
     * @param selfComp
     *            弹出控件标的控件
     * @param position
     *            位置
     * @param popCompUrl
     *            zul url
     * @param args
     *            参数
     * @param w
     *            width
     * @param h
     *            height
     * @return Window PopWarper Window
     */
    public static Window createOverlapped(final String popCompUrl, final Map<String, Object> args,
        final String w, final String h, final Component selfComp, final String position) {
        // get popup win
        Window popWin = ZkWindUtil.getAutoWind(selfComp, position);
        Window subWin;
        if (popWin == null) {
            // create real win
            subWin = (Window) Executions.createComponents(popCompUrl, null, args);
            popWin = ZkWindUtil.putAutoWind(selfComp, position, subWin);
        } else {
            subWin = (Window) popWin.getFirstChild();
        }
        // opoup
        subWin.setPosition("parent");
        // popWin.doOverlapped();
        ZkWindUtil.doOverlapped(subWin, w, h);
        return popWin;
    }
    
    /**
     * 生成嵌入窗口.
     * 
     * @param selfComp
     *            弹出控件标的控件
     * @param position
     *            位置
     * @param popCompUrl
     *            zul url
     * @param args
     *            参数
     * @param w
     *            width
     * @param h
     *            height
     * @return Window PopWarper Window
     */
    public static Window createEmbedded(final String popCompUrl, final Map<String, Object> args,
        final String w, final String h, final Component selfComp, final String position) {
        // get popup win
        Window popWin = ZkWindUtil.getAutoWind(selfComp, position);
        if (popWin == null) {
            // create real win
            final Window subWin = (Window) Executions.createComponents(popCompUrl, null, args);
            popWin = ZkWindUtil.putAutoWind(selfComp, position, subWin);
        }
        // opoup
        popWin.doEmbedded();
        // ZkWindUtil.doPopup((Window) popWin.getFirstChild(), w, h);
        return popWin;
    }
    
    /**
     * doModal.
     * 
     * @param win
     *            Window
     * @param size
     *            size
     */
    public static void doEmbedded(final Window win, final int size) {
        if (win == null) {
            throw new RtManagerException("打开窗口异常，传入的窗口为空", ZkWindUtil.class, "doModal", "winNull");
        }
        win.setClosable(true);
        win.setSizable(true);
        if (size == ZkWindUtil.WIN_MAX_SIZE) {
            ZkWindUtil.doEmbedded(win, ZkWindUtil.WIN_MAX_WIDTH_STR, ZkWindUtil.WIN_MAX_HEIGHT_STR);
        } else if (size == ZkWindUtil.WIN_MIN_SIZE) {
            ZkWindUtil.doEmbedded(win, ZkWindUtil.WIN_MIN_WIDTH_STR, ZkWindUtil.WIN_MIN_HEIGHT_STR);
        } else {
            ZkWindUtil.doEmbedded(win, ZkWindUtil.WIN_MID_WIDTH_STR, ZkWindUtil.WIN_MID_HEIGHT_STR);
        }
    }
    
    /**
     * doModal.
     * 
     * @param win
     *            Window
     * @param w
     *            String
     * @param h
     *            String
     */
    public static void doEmbedded(final Window win, final String w, final String h) {
        if (!ZkWindUtil.WIN_AUTO_SIZE_STR.equals(w)) {
            win.setWidth(w);
        }
        if (!ZkWindUtil.WIN_AUTO_SIZE_STR.equals(h)) {
            win.setHeight(h);
        }
        win.doEmbedded();
    }
    
    /**
     * getAutoWind.
     * 
     * @param selfComp
     *            定位组件
     * @param position
     *            prev,next
     * @return Window
     */
    public static Window getAutoWind(final Component selfComp, final String position) {
        Component preComp = null;
        if (ZkWindUtil.POSITION_PREV.equals(position)) {
            preComp = selfComp.getPreviousSibling();
            if (preComp != null && preComp.hasAttribute(ZkWindUtil.POP_CONTAINER)) {
                if (preComp.getChildren() != null && preComp.getChildren().size() > 0) {
                    return (Window) preComp;
                }
            }
        } else if (ZkWindUtil.POSITION_NEXT.equals(position)) {
            preComp = selfComp.getNextSibling();
            if (preComp != null && preComp.hasAttribute(ZkWindUtil.POP_CONTAINER)) {
                if (preComp.getChildren() != null && preComp.getChildren().size() > 0) {
                    return (Window) preComp;
                }
            }
        } else {
            throw new RtManagerException("传入参数position：@position错误，请确认", ZkWindUtil.class,
                "getPopWind", "PositionNull");
        }
        return null;
    }
    
    /**
     * getPopWind.
     * 
     * @param selfComp
     *            定位组件
     * @param position
     *            prev,next
     * @param popComp
     *            Component
     * @return Window
     */
    public static Window putAutoWind(final Component selfComp, final String position,
        final Component popComp) {
        Component preComp = null;
        if (ZkWindUtil.POSITION_PREV.equals(position)) {
            preComp = selfComp.getNextSibling();
            if (preComp != null && preComp.hasAttribute(ZkWindUtil.POP_CONTAINER)) {
                popComp.setParent(preComp);
                return (Window) preComp;
            } else {
                final Window popWin = new Window();
                popWin.setAttribute(ZkWindUtil.POP_CONTAINER, 1);
                popWin.setPosition("parent");
                selfComp.getParent().insertBefore(popWin, selfComp);
                popComp.setParent(popWin);
                return popWin;
            }
        } else if (ZkWindUtil.POSITION_NEXT.equals(position)) {
            preComp = selfComp.getNextSibling();
            if (preComp != null && preComp.hasAttribute(ZkWindUtil.POP_CONTAINER)) {
                popComp.setParent(preComp);
                return (Window) preComp;
            } else {
                final Window popWin = new Window();
                popWin.setAttribute(ZkWindUtil.POP_CONTAINER, 1);
                popWin.setPosition("parent");
                popWin.setParent(selfComp.getParent());
                selfComp.getParent().insertBefore(selfComp, popWin);
                popComp.setParent(popWin);
                return popWin;
            }
        } else {
            throw new RtManagerException("传入参数position：@position错误，请确认", ZkWindUtil.class,
                "getPopWind", "PositionNull");
        }
    }
    
    /**
     * 填充页面到ifram或者window.
     * 
     * @param parentComp
     *            Component
     * @param pageUrl
     *            String
     * @param args
     *            HashMap<String, Object>
     * @author wuyx
     *         iframe或者window填充工具
     *         判断父亲控件是Iframe还是Window
     *         如果是Iframe，按照iframe进行填充
     *         如果是Window，将Url进行截取，将参数存放到zul arg中，并清除旧有的控件，填充新控件
     *         待完善：如果填充的不是zul页面不允许按照Window方式进行
     */
    @SuppressWarnings("unchecked")
    public static void fillContainerPage(final Component parentComp, String pageUrl,
        Map<String, Object> args) {
        ZkWindUtil.fillContainerPage(parentComp, pageUrl, args, null);
    }
    
    /**
     * 填充页面到ifram或者window.
     * 
     * @param parentComp
     *            Component
     * @param pageUrl
     *            String
     * @param args
     *            HashMap<String, Object>
     * @author wuyx
     *         iframe或者window填充工具
     *         判断父亲控件是Iframe还是Window
     *         如果是Iframe，按照iframe进行填充
     *         如果是Window，将Url进行截取，将参数存放到zul arg中，并清除旧有的控件，填充新控件
     *         待完善：如果填充的不是zul页面不允许按照Window方式进行
     */
    @SuppressWarnings("unchecked")
    public static void fillContainerPage(final Component parentComp, String pageUrl,
        Map<String, Object> args, String fillTarget) {
        if (fillTarget != null && (WIN_OP_TYPE_OPEN.equals(fillTarget) || WIN_OP_TYPE_SELF.equals(fillTarget))) {
            final String npageUrl = ((pageUrl + "").indexOf("?") > -1) ? pageUrl
                + ZkUiUtil.getTimeSpan("&")
                : pageUrl + ZkUiUtil.getTimeSpan("?");
            if ("open".equals(fillTarget)) {
                ClientUtil.open(npageUrl, "", "");
            } else if ("self".equals(fillTarget)) {
                try {
                    ZkUtils.forward(npageUrl);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } else if (parentComp instanceof Iframe) {
            final String npageUrl = ((pageUrl + "").indexOf("?") > -1) ? pageUrl
                + ZkUiUtil.getTimeSpan("&")
                : pageUrl + ZkUiUtil.getTimeSpan("?");
            ((Iframe) parentComp).setSrc(npageUrl);
        } else if (parentComp instanceof Window) {
            final List<Component> childComp = parentComp.getChildren();
            if (childComp != null && childComp.size() > 0) {
                parentComp.getChildren().clear();
            }
            if (args == null) {
                args = new HashMap<String, Object>();
            }
            if ((pageUrl + "").indexOf("?") > -1) {
                final String[] strs = (pageUrl + "").split("\\?");
                if (strs.length > 1) { // ?后面数据
                    final String paramStr = strs[1];
                    final String[] paramStrs = paramStr.split("&");
                    final int sum = paramStrs.length;
                    for (int j = 0; j < sum; j++) { // 每个&数据
                        if (("" + paramStrs[j]).equals("")) { // 空数据，继续
                            continue;
                        }
                        final String[] oneStrs = ("" + paramStrs[j]).split("=");
                        args.put(ZkUtils.ZUL_PLUS_PARAMETER_PREFIX + oneStrs[0],
                            oneStrs.length > 1 ? oneStrs[1]
                                : "");
                    }
                }
                pageUrl = strs[0];
            }
            Executions.createComponents(pageUrl, parentComp, args);
        }
    }
    
    /**
     * .
     * 
     * @param parentComp Component
     * @param pageUrl String
     * @param args Map<String, Object>
     * @return Component
     * @author wuyx
     * 2011-4-28 wuyx 
     */
    public static Component createComponentsWithUrlParams(final Component parentComp,
        String pageUrl, Map<String, Object> args) {
        if (args == null) {
            args = new HashMap<String, Object>();
        }
        if ((pageUrl + "").indexOf("?") > -1) {
            final String[] strs = (pageUrl + "").split("\\?");
            if (strs.length > 1) { // ?后面数据
                final String paramStr = strs[1];
                final String[] paramStrs = paramStr.split("&");
                final int sum = paramStrs.length;
                for (int j = 0; j < sum; j++) { // 每个&数据
                    if (("" + paramStrs[j]).equals("")) { // 空数据，继续
                        continue;
                    }
                    final String[] oneStrs = ("" + paramStrs[j]).split("=");
                    args.put(ZkUtils.ZUL_PLUS_PARAMETER_PREFIX + oneStrs[0],
                        oneStrs.length > 1 ? oneStrs[1]
                            : "");
                }
            }
            pageUrl = strs[0];
        }
        return Executions.createComponents(pageUrl, parentComp, args);
    }
    
    /**
     * doClose.
     * 
     * @param comp Component
     * @author wuyx
     */
    public static void doClose(final Component comp) {
        if (comp instanceof Window) {
            Window win = (Window) comp;
            String mode = win.getMode() + "";
            if ("modal".equals(mode)) {
                Events.postEvent(new Event(Events.ON_CLOSE, comp));
            } else {
                comp.setVisible(false);
            }
        } else {
            comp.setVisible(false);
        }
    }
    
    /**
     * doReomveClose.
     * 
     * @param comp Component
     * @author wuyx
     */
    public static void doReomveClose(final Component comp) {
        Events.postEvent(new Event(Events.ON_CLOSE, comp));
    }
}
